home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / util / FaxDB.c++ < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  234 lines

  1. /*    $Header: /usr/people/sam/fax/util/RCS/FaxDB.c++,v 1.14 1994/02/28 14:24:13 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include "FaxDB.h"
  26. #include <InterViews/regexp.h>
  27.  
  28. FaxDBRecord::FaxDBRecord()
  29. {
  30.     parent = 0;
  31. }
  32.  
  33. FaxDBRecord::FaxDBRecord(FaxDBRecord* other)
  34. {
  35.     if (parent = other)
  36.     parent->inc();
  37. }
  38.  
  39. FaxDBRecord::~FaxDBRecord()
  40. {
  41.     if (parent)
  42.     parent->dec();
  43. }
  44.  
  45. const char* FaxDBRecord::className() const { return "FaxDBRecord"; }
  46.  
  47. fxStr FaxDBRecord::nullStr("");
  48.  
  49. const fxStr&
  50. FaxDBRecord::find(const fxStr& key)
  51. {
  52.     fxStr* s = 0;
  53.     FaxDBRecord* rec = this;
  54.     for (; rec && !(s = rec->dict.find(key)); rec = rec->parent)
  55.     ;
  56.     return (s ? *s : nullStr);
  57. }
  58.  
  59. void FaxDBRecord::set(const fxStr& key, const fxStr& value)
  60.     { dict[key] = value; }
  61.  
  62. fxIMPLEMENT_StrKeyObjValueDictionary(FaxValueDict, fxStr);
  63.  
  64. FaxDB::FaxDB(const fxStr& file) : filename(file)
  65. {
  66.     FILE* fd = fopen(file, "r");
  67.     if (fd) {
  68.     lineno = 0;
  69.     parseDatabase(fd, 0);
  70.     fclose(fd);
  71.     }
  72. }
  73.  
  74. FaxDB::~FaxDB()
  75. {
  76. }
  77.  
  78. const char* FaxDB::className() const { return "FaxDB"; }
  79.  
  80. fxStr FaxDB::nameKey("Name");
  81. fxStr FaxDB::numberKey("FAX-Number");
  82. fxStr FaxDB::companyKey("Company");
  83. fxStr FaxDB::locationKey("Location");
  84. fxStr FaxDB::phoneKey("Voice-Number");
  85.  
  86. FaxDBRecord*
  87. FaxDB::find(const fxStr& s, fxStr* name)
  88. {
  89.     fxStr canon(s);
  90.     canon.lowercase();
  91.     for (u_int l = 0; l < canon.length(); l = canon.next(l, "+?*[].\\")) {
  92.     canon.insert('\\', l);
  93.     l += 2;
  94.     }
  95.     Regexp pat(canon);
  96.     for (FaxInfoDictIter iter(dict); iter.notDone(); iter++) {
  97.     fxStr t(iter.key());
  98.     t.lowercase();
  99.     if (pat.Search(t, t.length(), 0, t.length()) >= 0) {
  100.         if (name)
  101.         *name = iter.key();
  102.         return (iter.value());
  103.     }
  104.     }
  105.     return (0);
  106. }
  107.  
  108. FaxDBRecord* FaxDB::operator[](const fxStr& name)    { return dict[name]; }
  109. const fxStr& FaxDB::getFilename()            { return filename; }
  110. FaxInfoDict& FaxDB::getDict()                { return dict; }
  111. void FaxDB::add(const fxStr& key, FaxDBRecord* r)    { dict[key] = r; }
  112.  
  113. void
  114. FaxDB::parseDatabase(FILE* fd, FaxDBRecord* parent)
  115. {
  116.     FaxDBRecordPtr rec(new FaxDBRecord(parent));
  117.     fxStr key;
  118.     while (getToken(fd, key)) {
  119.     if (key == "]") {
  120.         if (parent == 0)
  121.         fprintf(stderr, "%s: line %d: Unmatched \"]\".\n",
  122.             (char*) filename, lineno);
  123.         break;
  124.     }
  125.     if (key == "[") {
  126.         parseDatabase(fd, rec);            // recurse to form hierarchy
  127.         continue;
  128.     }
  129.     fxStr value;
  130.     if (!getToken(fd, value))
  131.         break;
  132.     if (value != ":") {
  133.         fprintf(stderr, "%s: line %d: Missing \":\" separator.\n",
  134.         (char*) filename, lineno);
  135.         continue;
  136.     }
  137.     if (!getToken(fd, value))
  138.         break;
  139.     rec->set(key, value);
  140.     if (key == nameKey)            // XXX what about duplicates?
  141.         add(value, rec);
  142.     }
  143. }
  144.  
  145. #include "StackBuffer.h"
  146. #include <ctype.h>
  147.  
  148. fxBool
  149. FaxDB::getToken(FILE* fd, fxStr& token)
  150. {
  151.     int c;
  152. top:
  153.     if ((c = getc(fd)) == EOF)
  154.     return (FALSE);
  155.     while (isspace(c)) {
  156.     if (c == '\n')
  157.         lineno++;
  158.     c = getc(fd);
  159.     }
  160.     if (c == '#') {
  161.     while ((c = getc(fd)) != EOF && c != '\n')
  162.         ;
  163.     if (c == EOF)
  164.         return (FALSE);
  165.     lineno++;
  166.     goto top;
  167.     }
  168.     if (c == '[' || c == ']' || c == ':') {
  169.     char buf[2];
  170.     buf[0] = c;
  171.     buf[1] = '\0';
  172.     token = buf;
  173.     return (TRUE);
  174.     }
  175.     fxStackBuffer buf;
  176.     if (c == '"') {
  177.     while ((c = getc(fd)) != EOF) {
  178.         if (c == '\\') {
  179.         c = getc(fd);
  180.         if (c == EOF) {
  181.             fprintf(stderr, "%s: Premature EOF.\n", (char*) filename);
  182.             return (FALSE);
  183.         }
  184.         // XXX handle standard escapes
  185.         if (c == '\n')
  186.             lineno++;
  187.         } else {
  188.         if (c == '"')
  189.             break;
  190.         if (c == '\n')
  191.             lineno++;
  192.         }
  193.         buf.put(c);
  194.     }
  195.     } else {
  196.     do
  197.         buf.put(c);
  198.     while ((c = getc(fd)) != EOF && !isspace(c) &&
  199.       c != ':' && c != ']' && c != '[' && c != '#');
  200.     if (c != EOF)
  201.         ungetc(c, fd);
  202.     }
  203.     buf.set('\0');
  204.     token = (char*) buf;
  205.     return (TRUE);
  206. }
  207.  
  208. #ifdef notdef
  209. void
  210. FaxDB::write()
  211. {
  212.     fxStr temp(filename | "#");
  213.     FILE* fp = fopen(temp, "w");
  214.     if (fp) {
  215.     write(fp);
  216.     fclose(fp);
  217.     ::rename(temp, filename);
  218.     }
  219. }
  220.  
  221. void
  222. FaxDB::write(FILE* fp)
  223. {
  224.     for (FaxInfoDictIter iter(dict); iter.notDone(); iter++) {
  225.     fprintf(fp, "[ Name: \"%s\"\n", (char*) iter.key());
  226.     FaxDBRecord* r = iter.value();
  227.     const fxStr& 
  228.     fprintf(fp, "]\n");
  229.     }
  230. }
  231. #endif
  232.  
  233. fxIMPLEMENT_StrKeyPtrValueDictionary(FaxInfoDict, FaxDBRecord*);
  234.